package com.zhangjianling.premp.controller.sys;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhangjianling.premp.entity.sys.SysLog;
import com.zhangjianling.premp.entity.sys.SysUser;
import com.zhangjianling.premp.server.sys.SysLogService;
import com.zhangjianling.premp.utils.RequestIPUtil;
import com.zhangjianling.premp.utils.SystemAopLog;
import com.zhangjianling.premp.utils.TimeHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
/**
 * 切面日志管理
 * @author zhangjl
 *
 */
@Aspect  
@Component
@Order(0)
public class SystemLogAspect<order> {
	@Resource
	private SysLogService sysLogService;
	
	public SystemLogAspect() {
		System.out.println("执行aop。。。。。。。");
	}
	
	@Pointcut("@annotation(com.zhangjianling.premp.utils.SystemAopLog)")
	public void systemAopLog() {  
		System.out.println("========SystemAopLog===========");  
	}  
	 
    /** 
     * 前置通知 用于拦截Controller层操作  
     * @param joinPoint 切点 
     */  
    @Before("systemAopLog()")  
    private void doBefore(JoinPoint joinPoint) {  
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        // 获取登陆用户信息  
        Subject currentUser = SecurityUtils.getSubject();
        SysUser user =  (SysUser)currentUser.getPrincipal();
        String curUserName =  user!=null ?user.getUserName():(String)currentUser.getPrincipal();
        // 获取请求ip  
        String ip = RequestIPUtil.getClientIp(request);
        try {
        	String params = "";  
            Object[] args = joinPoint.getArgs();  
            if (args != null) {  
            	ObjectMapper mapper = new ObjectMapper();
            	params = mapper.writeValueAsString(args[0]);
            }
            if(!StringUtils.isNotBlank(curUserName)){
            	curUserName = "匿名用户";
            }
            // *========数据库日志=========*//  
            SysLog log = new SysLog();
            log.setDescription(getMethodDescription(joinPoint)+"-操作成功");
            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            log.setType("0");  
            log.setRequestIp(ip);
            log.setExceptionCode(null);  
            log.setExceptionDetail(null);  
            log.setParams(params);  
            log.setUserName(curUserName);  
            log.setCreateDate(TimeHelper.getCurrentTime());
            // 保存数据库  
            sysLogService.save(log);  
        } catch (Exception e) {  
            // 记录本地异常日志  
            e.printStackTrace();
        }  
    }  
    
    /** 
     * 异常通知
     * @param joinPoint
     * @param e
     * @throws JsonProcessingException 
     */
    @AfterThrowing(pointcut = "systemAopLog()", throwing="e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) throws JsonProcessingException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
                .getRequestAttributes()).getRequest();  
        // 获取登陆用户信息  
        Subject subject = SecurityUtils.getSubject();
        SysUser currentUser = (SysUser)subject.getPrincipal();
        String curUserName =  currentUser!=null?currentUser.getUserName():(String)subject.getPrincipal();
        // 获取请求ip  
        String ip = RequestIPUtil.getClientIp(request);  
        // 获取用户请求方法的参数并序列化为JSON格式字符串  
        String params = "";  
        Object[] args = joinPoint.getArgs();
        if (args != null) {
        	ObjectMapper mapper = new ObjectMapper();
        	params = mapper.writeValueAsString(args[0]);
        }
        try {  
            /* ==========数据库日志========= */  
            SysLog log = new SysLog();
            log.setDescription(getMethodDescription(joinPoint)+"-操作失败");
            log.setExceptionCode(e.getMessage());
            log.setType("1");
            log.setExceptionDetail(e.getCause().getCause().getMessage());
            log.setMethod((joinPoint.getTarget().getClass().getName() + "."
                    + joinPoint.getSignature().getName() + "()"));
            log.setParams(params);
            log.setUserName(curUserName);
            log.setCreateDate(TimeHelper.getCurrentTime());
            log.setRequestIp(ip);
            // 保存数据库  
            sysLogService.save(log);  
            System.out.println("=====异常通知结束=====");  
        } catch (Exception ex) {  
            // 记录本地异常日志  
           ex.printStackTrace();
        }
    } 
    
    /** 
     * 获取注解中对方法的描述信息
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */  
    public static String getMethodDescription(JoinPoint joinPoint) throws Exception{  
        //获取方法名  
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SystemAopLog aopLog = method.getAnnotation(SystemAopLog.class);
        return aopLog.description();  
    }  
}
